package link.ui.uc;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.orhanobut.logger.Logger;
import link.api.LinkApi;
import link.config.AgentConfig;
import link.config.StoreConfig;
import link.config.UIConfig;
import link.model.AgentInfoVo;
import link.model.ConfigInfoVo;
import link.model.TokenInfoVo;
import link.model.request.LoginRequestInfo;
import org.an.ku.util.ToastUtil;
import org.an.ku.view.MyTextView;
import org.an.proj.contacts.MyApplication;
import org.an.proj.contacts.R;
import org.an.proj.contacts.model.response.Result;
import org.an.proj.contacts.net.service.retrofit.util.ServiceGenerator;
import org.an.proj.contacts.net.service.rx.ResultSubscriber;
import org.an.proj.contacts.ui.MainActivity;
import org.an.proj.contacts.ui.base.BaseActivity;
import org.an.proj.contacts.util.CollectionUtil;
import org.an.proj.contacts.util.ConstantUtil;
import org.an.proj.contacts.util.DeviceUtil;
import org.an.proj.contacts.util.IntentUtil;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Func2;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;

import static org.an.proj.contacts.R.id.ll_auth_code;

public class LoginActivity extends BaseActivity {

  @Bind(R.id.et_username) EditText mEtUsername;
  @Bind(R.id.et_password) EditText mEtPassword;
  @Bind(R.id.tv_auth_msg) MyTextView mTvAuthMsg;
  @Bind(R.id.tv_phone_wrong) MyTextView mTvPhoneWrong;
  @Bind(R.id.et_auth_code) EditText mEtAuthCode;
  @Bind(R.id.tv_no_receive) MyTextView mTvNoReceive;
  @Bind(R.id.tv_resend) MyTextView mTvResend;
  @Bind(ll_auth_code) LinearLayout mLlAuthCode;

  private Observable<Result<TokenInfoVo>> mTokenObservable;
  private final String CHANNEL = "linknh";

  private LoginRequestInfo mLoginRequestInfo = new LoginRequestInfo();
  private CompositeSubscription mSubscriptions;// 管理所有的订阅

  @Override protected boolean isFull() {
    return true;
  }

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSubscriptions = new CompositeSubscription();
    mLoginRequestInfo.channel = CHANNEL;
    mLoginRequestInfo.devId = DeviceUtil.getUUID(this);
    setContentView(R.layout.activity_login);
    ButterKnife.bind(this);
  }

  @OnClick(R.id.iv_logo) public void onClick() {
    ConfigInfoVo configInfo = UIConfig.getInstance().getConfigInfo();
    AgentInfoVo agentInfo = AgentConfig.getInstance().getAgentInfo();
  }

  /**
   * 点击登录
   */
  @OnClick(R.id.btn_login) public void onLogin() {
    //if (StoreConfig.getInstance().getToken() != null) {
    //  loadConfig();
    //  return;
    //}

    String userName = mEtUsername.getText().toString().trim();
    String password = mEtPassword.getText().toString().trim();
    String authCode = null;
    mLoginRequestInfo.userCode = userName;
    mLoginRequestInfo.pwd = password;
    if (mLlAuthCode.getVisibility() == View.VISIBLE) {
      authCode = mEtAuthCode.getText().toString().trim();
      mLoginRequestInfo.code = authCode;
    }
    mTokenObservable = ServiceGenerator.createMobileService(LinkApi.class)
        .appLogin(CollectionUtil.object2Map(mLoginRequestInfo));

    Subscription subscribe =
        mTokenObservable.subscribeOn(Schedulers.io())// 指定 subscribe() 发生在 IO 线程
            //.subscribeOn(
            //  AndroidSchedulers.mainThread()) // 如果在doOnSubscribe()之后指定了subscribeOn()，它决定了doOnSubscribe()在哪种线程中执行
            .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程
            .doOnSubscribe(new Action0() {
              @Override public void call() {
                // 需要在主线程执行，执行前加载
                showLoadingBar();
              }
            }).subscribe(new ResultSubscriber<TokenInfoVo>() {
          @Override public void onResponse(Result<TokenInfoVo> result, @Nullable Throwable error) {
            if (result != null) {
              if (result.errno == ConstantUtil.ERRNO_SMS_AUTHOR) {
                loginWidthAuthCode();
              } else if (result.hasData() && result.data.token != null) {
                //  登录成功，存储token
                StoreConfig.getInstance().setToken(result.data.token);
                loadConfig();
              } else if (result.error != null) {
                dismissLoadingBar();
                ToastUtil.toast(MyApplication.getInstance(), result.error);
              } else {
                dismissLoadingBar();
                loginError();
              }
            } else {
              dismissLoadingBar();
              loginError();
            }
          }
        });
    mSubscriptions.add(subscribe);
  }

  private void loginWidthAuthCode() {
    dismissLoadingBar();
    // 此次登录需要验证码
    ToastUtil.toast(mContext, R.string.auth_code_is_sending);
    mLlAuthCode.setVisibility(View.VISIBLE);
  }

  private void loginError() {
    Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
  }

  private boolean checkConfig(Result<ConfigInfoVo> result) {
    return (result != null
        && result.hasData()
        && result.data.configNewHouse != null
        && !CollectionUtil.isEmpty(result.data.configNewHouse.tab));
  }

  /**
   * 拉取经纪人信息和配置信息
   * fixme 这个是不是可以用retry,当失败
   */
  private void loadConfig() {
    Observable<Result<AgentInfoVo>> agentObservable =
        ServiceGenerator.createService(LinkApi.class).userLogin(CHANNEL);
    Observable<Result<ConfigInfoVo>> configObservable =
        ServiceGenerator.createService(LinkApi.class).getConfigInfoVo();

    // zip是串行的，任意一个失败的话，不会回调Func2的call方法
    Observable.zip(agentObservable, configObservable,
        new Func2<Result<AgentInfoVo>, Result<ConfigInfoVo>, Boolean>() {
          @Override public Boolean call(Result<AgentInfoVo> agentInfoResult,
              Result<ConfigInfoVo> configInfoVoResult) {
            Logger.e("zip..................");
            if (agentInfoResult != null && checkConfig(configInfoVoResult)) {
              // 两个数据都有效才认为是登录成功
              // 保存经纪人信息和config信息到sp中
              UIConfig.getInstance().setConfigInfo(configInfoVoResult.data);
              AgentConfig.getInstance().setAgentInfo(agentInfoResult.data);
              return true;
            }
            return false;
          }
        })
        .retry(3)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<Boolean>() {
          @Override public void onCompleted() {

          }

          @Override public void onError(Throwable e) {
            onNext(false);
          }

          @Override public void onNext(Boolean isSuccess) {
            dismissLoadingBar();
            if (isSuccess) {
              loginSuccess();
            } else {
              loginError();
            }
          }
        });
  }

  /**
   * 登录成功
   */
  private void loginSuccess() {
    ToastUtil.toast(mContext, "登录成功");
    StoreConfig.getInstance().setLogin(true);
    IntentUtil.goToOthersF(mContext, MainActivity.class);
  }

  @Override protected void onDestroy() {
    if (mSubscriptions != null) {
      mSubscriptions.unsubscribe();
    }
    super.onDestroy();
  }
}
